package com.siecom.transport.handler;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.google.gson.Gson;
import com.google.protobuf.ByteString;
import com.siecom.constconfig.ConstDefine;
import com.siecom.constconfig.ErrorDefine;
import com.siecom.hostservice.MainActivity;
import com.siecom.module.DeviceCallback;
import com.siecom.module.DeviceInterface;
import com.siecom.proto.Message;
import com.siecom.signaturepad.views.SignaturePad;
import com.siecom.tool.ByteTool;
import com.siecom.tool.LogUtil;
import com.siecom.transport.CommServer;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by zhq on 2017/2/6.
 */

public class SignatureHandler implements ServiceHandler {
    private static ExecutorService threadPool = Executors.newFixedThreadPool(1);
    private static final String TAG = "SignatureHandler";

    private CommServer server;
    private Timer timer;

    @Override
    public void onReceive(CommServer server, Message.siecomproto msg,String message) {
        this.server = server;
        Log.e("SignatureHandler", "onReceive");
        disposeMessage(msg);
    }


    public void disposeMessage(Message.siecomproto msg) {

        switch (msg.getCmd()) {
            case ConstDefine.SIGNATURE_SM4_REQUEST:

                setSM4PrimaryKey(msg);

                break;

            case  ConstDefine.SIGNATURE_SM2_REQUEST:
                transSM2PublicKey(msg);
                break;
            case ConstDefine.SIGNATURE_REQUEST:
                signature(msg);
                break;
            case ConstDefine.SIGNATURE_CANCEL_REQUEST:
                cancelTask(msg);
                break;

        }

    }

    private void setSM4PrimaryKey(Message.siecomproto msg) {
        byte[] sm4 = msg.getExtion().toByteArray();
        DeviceInterface.setSM4PrimaryKey(new DeviceCallback() {
          @Override
          public void onStart() {

          }

          @Override
          public void onError(Bundle bundle) {
              com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
              Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
              msgBuilder.setModule(msg.getModule());
              msgBuilder.setMsgid(msg.getMsgid());
              msgBuilder.setCmd(msg.getCmd() + 1);
              msgBuilder.setRespond(bundle.getString("message"));
              msgBuilder.setError(bundle.getInt("code"));
              com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
              server.sendToRemote(respondMsg);
              MainActivity.playVoice(ConstDefine.OPERATE_FAIL);
          }

          @Override
          public void onSuccess(Bundle bundle) {
              com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
              Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
              msgBuilder.setModule(msg.getModule());
              msgBuilder.setMsgid(msg.getMsgid());
              msgBuilder.setCmd(msg.getCmd() + 1);
              msgBuilder.setRespond(bundle.getString("data"));
              msgBuilder.setError(0);
              com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
              server.sendToRemote(respondMsg);
              MainActivity.playVoice(ConstDefine.OPERATE_SUCC);
          }

          @Override
          public void onCompleted(Bundle bundle) {

          }
      },sm4,false);

    }

    public void transSM2PublicKey(Message.siecomproto msg){
        DeviceInterface.transSM2PublicKey(new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
                msgBuilder.setModule(msg.getModule());
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setCmd(msg.getCmd() + 1);
                msgBuilder.setRespond(bundle.getString("message"));
                msgBuilder.setError(bundle.getInt("code"));
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);

            }

            @Override
            public void onSuccess(Bundle bundle) {
                com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
                msgBuilder.setModule(msg.getModule());
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setCmd(msg.getCmd() + 1);
                msgBuilder.setRespond(bundle.getString("data"));
                msgBuilder.setError(0);
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);
            }

            @Override
            public void onCompleted(Bundle bundle) {

            }
        },false);

    }

    public void cancelTask(Message.siecomproto msg){

        com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
        Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
        msgBuilder.setModule(msg.getModule());
        msgBuilder.setMsgid(msg.getMsgid());
        msgBuilder.setCmd(msg.getCmd() + 1);
        msgBuilder.setRespond("signature cancel");
        msgBuilder.setError(0);
        com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
        server.sendToRemote(respondMsg);
        MainActivity.cancelSignaturePad();
        if(timer!=null){
            timer.cancel();
        }

    }
    private void signature(Message.siecomproto msg){
        //解析发过的参数数据
        JSONObject json = null;
        String hint = "";
        int rgb = 0;
        try {
            json = new JSONObject(msg.getRequest());
            hint = json.getString("hintMsg"); // 密码
            rgb = json.getInt("rgb");

        } catch (JSONException e) {
            e.printStackTrace();
        }
        MainActivity.showSignaturePad( msg.getTimeout(),hint,rgb);

        /**
         * 超时处理
         */
        TimerTask task = new TimerTask() {
            @Override
            public void run() {

                Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setModule(msg.getModule());
                msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
                msgBuilder.setError(ErrorDefine.SIGNATURE_TIMEOUT);
                msgBuilder.setRespond(ErrorDefine.getErrorDescribe(ErrorDefine.SIGNATURE_TIMEOUT));
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);

                MainActivity.cancelSignaturePad();
            }
        };
        if(timer!=null){
            timer.cancel();
        }
        timer = new Timer();
        timer.schedule(task, msg.getTimeout());



        MainActivity.setSignatureListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(MainActivity.isClean){
                    MainActivity.playVoice(7);
                    return;
                }

                v.setEnabled(false);
                Runnable r = new Runnable() {
                    @Override
                    public void run() {

                        MainActivity.endSignature(new MainActivity.SignatureCallball(){

                            @Override
                            public void endSign(int res, byte[] data) {

                                if(res==0x90){
                                    Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                                    msgBuilder.setMsgid(msg.getMsgid());
                                    msgBuilder.setModule(msg.getModule());
                                    msgBuilder.setRespond("sign");
                                    msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
                                    msgBuilder.setError(0);
                                    ByteString signByte = ByteString.copyFrom(data);
                                    msgBuilder.setExtion(signByte);
                                    Message.siecomproto respondMsg = msgBuilder.build();
//                                    server.sendToRemote(respondMsg);
                                }else if(res == 10086){
                                    Message.siecomproto.Builder msgBuilderData = com.siecom.proto.Message.siecomproto.newBuilder();
                                    msgBuilderData.setMsgid(msg.getMsgid());
                                    msgBuilderData.setModule(msg.getModule());
                                    msgBuilderData.setRespond("UnencryptedTrack");
                                    msgBuilderData.setCmd(ConstDefine.SIGNATURE_RESPOND);
                                    msgBuilderData.setError(0);
                                    byte[] bytes = ByteTool.getInfoBytesFromObject(SignaturePad.mPoint);
                                    String p = new Gson().toJson(SignaturePad.mPoint);//以json方式传递
//                                    LogUtil.e(TAG,"GSON ==" + p);
                                    msgBuilderData.setRequest(p);//发送字符字节
//                                    ByteString signByte = ByteString.copyFrom(bytes);//发送
//                                    msgBuilderData.setExtion(signByte);
                                    Message.siecomproto respondMsgData = msgBuilderData.build();
//                                    server.sendToRemote(respondMsgData);

                                    MainActivity.cancelSignaturePad();

                                }else{
//                                    Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
//                                    msgBuilder.setMsgid(msg.getMsgid());
//                                    msgBuilder.setModule(msg.getModule());
//                                    msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
//                                    msgBuilder.setError(res);
//                                    msgBuilder.setRespond("sign_err");
//                                    ByteString signByte = ByteString.copyFrom(data);
//                                    msgBuilder.setExtion(signByte);
//                                    Message.siecomproto respondMsg = msgBuilder.build();
//                                    mBlueServer.sendToRemote(respondMsg);

                                }

                            }
                        });
//                        Message.siecomproto.Builder msgBuilderData = com.siecom.proto.Message.siecomproto.newBuilder();
//                        msgBuilderData.setMsgid(msg.getMsgid());
//                        msgBuilderData.setModule(msg.getModule());
//                        msgBuilderData.setRespond("UnencryptedTrack");
//                        msgBuilderData.setCmd(ConstDefine.SIGNATURE_RESPOND);
//                        msgBuilderData.setError(0);
//                        ByteString signByte = ByteString.copyFrom(ByteTool.getInfoBytesFromObject(SignaturePad.mPoint));
//                        msgBuilderData.setExtion(signByte);
//                        Message.siecomproto respondMsgData = msgBuilderData.build();
//                        mBlueServer.sendToRemote(respondMsgData);
                        //发送图片数据
                        sendSignBitmap(msg);

                        if(timer!=null){
                            timer.cancel();
                        }


                    }
                };
                threadPool.submit(r);


            }
        });

    }


    public void sendSignBitmap(Message.siecomproto msg){
        Log.e("setSignatureListener","click");

        Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
        msgBuilder.setMsgid(msg.getMsgid());
        msgBuilder.setModule(msg.getModule());
        msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
        msgBuilder.setError(0);
        msgBuilder.setRespond("");
        JSONObject jb;
        String scale = "";
        try {
            jb = new JSONObject(msg.getRequest());
            scale = jb.getString("scale");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        LogUtil.e(TAG,"scale == " + scale);
        if (TextUtils.isEmpty(scale)){
            scale = "2";
        }
        float s = Integer.parseInt(scale) * 0.1f;
        Bitmap signatureBmp = MainActivity.getSignaturePadBitmap();
        if(s > 0 && s < 1){
            signatureBmp = matrixCompress(signatureBmp,s); //大小压缩
        }
        //把边框白色部分消除
        signatureBmp = clearBlank(signatureBmp,1);

        ByteArrayOutputStream output = new ByteArrayOutputStream();//初始化一个流对象
        signatureBmp.compress(Bitmap.CompressFormat.PNG, 1, output);
        signatureBmp.recycle();//自由选择是否进行回收
        byte[] result = output.toByteArray();//转换成功了
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        ByteString bitmapByte = ByteString.copyFrom(result);
        msgBuilder.setExtion(bitmapByte);
        LogUtil.e(TAG,"签名图片大小：" + bitmapByte.size() );
//                        ByteString signByte = ByteString.copyFrom(ByteTool.getInfoBytesFromObject(SignaturePad.mPoint));
//                        msgBuilder.setMsgidBytes(bitmapByte);
        Message.siecomproto respondMsg = msgBuilder.build();
        server.sendToRemote(respondMsg);
    }

    public Bitmap matrixCompress(Bitmap bmp,float size){
        Matrix matrix = new Matrix();
        matrix.setScale(size,size);
        return Bitmap.createBitmap(bmp,0,0,bmp.getWidth(),bmp.getHeight(),matrix,true);
    }

    /**
     * 背景色（指最终签名结果文件的背景颜色）
     */
    private int mBackColor = Color.WHITE;
    /**
     * 逐行扫描 清楚边界空白。
     *
     * @param bp
     * @param blank 边距留多少个像素
     * @return
     */
    private Bitmap clearBlank(Bitmap bp, int blank) {
        int HEIGHT = bp.getHeight();
        int WIDTH = bp.getWidth();
        int top = 0, left = 0, right = 0, bottom = 0;
        int[] pixs = new int[WIDTH];
        boolean isStop;
        //扫描上边距不等于背景颜色的第一个点
        for (int y = 0; y < HEIGHT; y++) {
            bp.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1);
            isStop = false;
            for (int pix : pixs) {
                if (pix != mBackColor) {
                    top = y;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        //扫描下边距不等于背景颜色的第一个点
        for (int y = HEIGHT - 1; y >= 0; y--) {
            bp.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1);
            isStop = false;
            for (int pix : pixs) {
                if (pix != mBackColor) {
                    bottom = y;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        pixs = new int[HEIGHT];
        //扫描左边距不等于背景颜色的第一个点
        for (int x = 0; x < WIDTH; x++) {
            bp.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT);
            isStop = false;
            for (int pix : pixs) {
                if (pix != mBackColor) {
                    left = x;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        //扫描右边距不等于背景颜色的第一个点
        for (int x = WIDTH - 1; x > 0; x--) {
            bp.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT);
            isStop = false;
            for (int pix : pixs) {
                if (pix != mBackColor) {
                    right = x;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        if (blank < 0) {
            blank = 0;
        }
        //计算加上保留空白距离之后的图像大小
        left = left - blank > 0 ? left - blank : 0;
        top = top - blank > 0 ? top - blank : 0;
        right = right + blank > WIDTH - 1 ? WIDTH - 1 : right + blank;
        bottom = bottom + blank > HEIGHT - 1 ? HEIGHT - 1 : bottom + blank;
        return Bitmap.createBitmap(bp, left, top, right - left, bottom - top);
    }

}
